/*
 * Software for Interactive Project Pool Game
 * Columbia University. New York, 2008
 * Authors:
 *   Abdulhamid Ghandour
 *   Thomas John
 *   Jaime Peretzman
 *   Bharadwaj Vellore
 * 
 * Desc:
 */
#include <io.h>
#include <system.h>
#include <stdio.h>

#define IOWR_LED_DATA(base, offset, data)      IOWR_16DIRECT(base, (offset) * 2, data) 
#define IORD_LED_DATA(base, offset)            IORD_16DIRECT(base, (offset) * 2)
#define IOWR_LED_SPEED(base, data)             IOWR_16DIRECT(base + 32, 0, data)

#define IORD_I2C_TIMER(base, offset)           IORD_32DIRECT(base, (offset) * 4)
#define IOWR_I2C_REG(base, offset, data)       IOWR_32DIRECT(base, (offset) * 4, data)
#define IORD_I2C_REG(base, offset)             IORD_32DIRECT(base, (offset) * 4)

#define SCLK_SET                               IOWR_I2C_REG(CAMERA_BASE, 0, 0xFFFFFFFF)
#define SCLK_CLR                               IOWR_I2C_REG(CAMERA_BASE, 0, 0)
#define SDAT_SET                               IOWR_I2C_REG(CAMERA_BASE, 1, 3)
#define SDAT_CLR                               IOWR_I2C_REG(CAMERA_BASE, 1, 2)
#define SDAT_TRISTATE                          IOWR_I2C_REG(CAMERA_BASE, 1, 0)
#define RD_ACK                                 IORD_I2C_REG(CAMERA_BASE, 2)
#define CLR_ACK                                IOWR_I2C_REG(CAMERA_BASE, 2, 0)  

#define HALF_CLOCK_DELAY                       i+1;
#define ONE_CLOCK_DELAY                        i++; i--;                      
#define DELAY(x)                               for(i=0; i < (x); i++)

#include "i2c.h"

int configureCamera()
{
  volatile int i;
  int ack1, ack2, ack3, ack4, ack5, ack6;
  int bit0, bit1, bit2, bit3, bit4, bit5, bit6, bit7;
  int bit8, bit9, bit10, bit11, bit12, bit13, bit14, bit15;
  int version;

  SDAT_SET;
  SCLK_SET;
  DELAY(10000);
  
  COMM_INIT;
  READ_ACK(ack1);
  SEND_0;
  SEND_9;
  READ_ACK(ack2);

  START;
  SEND_B;
  SEND_B;
  READ_ACK(ack3);
  READ(bit0);
  READ(bit1);
  READ(bit2);
  READ(bit3);
  READ(bit4);
  READ(bit5);
  READ(bit6);
  READ(bit7);
  NACK;

  COMM_INIT;
  READ_ACK(ack4);
  SEND_F;
  SEND_1;
  READ_ACK(ack5);

  START;
  SEND_B;
  SEND_B;
  READ_ACK(ack6);
  READ(bit8);
  READ(bit9);
  READ(bit10);
  READ(bit11);
  READ(bit12);
  READ(bit13);
  READ(bit14);
  READ(bit15);
  NACK;

  STOP;
 
  printf("Ack 1: %d\n", ack1);
  printf("Ack 2: %d\n", ack2);
  printf("Ack 3: %d\n", ack3);
  printf("Ack 4: %d\n", ack4);
  printf("Ack 5: %d\n", ack5);
  printf("Ack 6: %d\n", ack6);
  
  version = (bit15 << 0) + (bit14 << 1) + (bit13 << 2) + (bit12 << 3) + 
            (bit11 << 4) + (bit10 << 5) + (bit9  << 6) + (bit8  << 7) +
            (bit7  << 8) + (bit6  << 9) + (bit5 << 10) + (bit4 << 11) +
            (bit3 << 12) + (bit2 << 13) + (bit1 << 14) + (bit0 << 15);
  
  printf("Version = 0x%x\n",version);

  /*
   * Write the exposure setting
   */
  COMM_INIT;      READ_ACK(ack1);
  SEND_0; SEND_9; READ_ACK(ack2);
  SEND_0; SEND_2; READ_ACK(ack3);

  COMM_INIT;      READ_ACK(ack4);
  SEND_F; SEND_1; READ_ACK(ack5);
  SEND_2; SEND_A; READ_ACK(ack6);
  STOP;

  DELAY(10000);

  /*
   * Write the row width
   */
  COMM_INIT;      READ_ACK(ack1);
  SEND_0; SEND_3; READ_ACK(ack2);
  SEND_0; SEND_1; READ_ACK(ack3);

  COMM_INIT;      READ_ACK(ack4);
  SEND_F; SEND_1; READ_ACK(ack5);
  SEND_E; SEND_0; READ_ACK(ack6);
  STOP;

  DELAY(10000);

  /*
   * Write the column width
   */
  COMM_INIT;      READ_ACK(ack1);
  SEND_0; SEND_4; READ_ACK(ack2);
  SEND_0; SEND_2; READ_ACK(ack3);

  COMM_INIT;      READ_ACK(ack4);
  SEND_F; SEND_1; READ_ACK(ack5);
  SEND_8; SEND_0; READ_ACK(ack6);
  STOP;

  DELAY(10000);

  /*
   * Write the horizontal blanking for mode B
   */
  COMM_INIT;      READ_ACK(ack1);
  SEND_0; SEND_5; READ_ACK(ack2);
  SEND_0; SEND_0; READ_ACK(ack3);

  COMM_INIT;      READ_ACK(ack4);
  SEND_F; SEND_1; READ_ACK(ack5);
  SEND_C; SEND_A; READ_ACK(ack6);
  STOP;

  DELAY(10000);
  
  /*
   * Write the row speed
   */
  COMM_INIT;      READ_ACK(ack1);
  SEND_0; SEND_A; READ_ACK(ack2);
  SEND_0; SEND_0; READ_ACK(ack3);

  COMM_INIT;      READ_ACK(ack4);
  SEND_F; SEND_1; READ_ACK(ack5);
  SEND_1; SEND_1; READ_ACK(ack6);
  STOP;

  DELAY(10000);

  /*
   * Write the vertical blanking for mode B
   */
  COMM_INIT;      READ_ACK(ack1);
  SEND_0; SEND_6; READ_ACK(ack2);
  SEND_0; SEND_0; READ_ACK(ack3);

  COMM_INIT;      READ_ACK(ack4);
  SEND_F; SEND_1; READ_ACK(ack5);
  SEND_1; SEND_9; READ_ACK(ack6);
  STOP;

  DELAY(10000);
  
  /*
   * Write the horizontal blanking for mode A
   */
  COMM_INIT;      READ_ACK(ack1);
  SEND_0; SEND_7; READ_ACK(ack2);
  SEND_0; SEND_0; READ_ACK(ack3);

  COMM_INIT;      READ_ACK(ack4);
  SEND_F; SEND_1; READ_ACK(ack5);
  SEND_8; SEND_8; READ_ACK(ack6);
  STOP;

  DELAY(10000);

  /*
   * Write the context control
   */
  COMM_INIT;      READ_ACK(ack1);
  SEND_C; SEND_8; READ_ACK(ack2);
  SEND_0; SEND_0; READ_ACK(ack3);

  COMM_INIT;      READ_ACK(ack4);
  SEND_F; SEND_1; READ_ACK(ack5);
  SEND_0; SEND_B; READ_ACK(ack6);
  STOP;

  DELAY(10000);
    COMM_INIT;
  READ_ACK(ack1);
  SEND_0;
  SEND_3;
  READ_ACK(ack2);

  START;
  SEND_B;
  SEND_B;
  READ_ACK(ack3);
  READ(bit0);
  READ(bit1);
  READ(bit2);
  READ(bit3);
  READ(bit4);
  READ(bit5);
  READ(bit6);
  READ(bit7);
  NACK;

  COMM_INIT;
  READ_ACK(ack4);
  SEND_F;
  SEND_1;
  READ_ACK(ack5);

  START;
  SEND_B;
  SEND_B;
  READ_ACK(ack6);
  READ(bit8);
  READ(bit9);
  READ(bit10);
  READ(bit11);
  READ(bit12);
  READ(bit13);
  READ(bit14);
  READ(bit15);
  NACK;

  STOP;
 
  printf("Ack 1: %d\n", ack1);
  printf("Ack 2: %d\n", ack2);
  printf("Ack 3: %d\n", ack3);
  printf("Ack 4: %d\n", ack4);
  printf("Ack 5: %d\n", ack5);
  printf("Ack 6: %d\n", ack6);
  
  version = (bit15 << 0) + (bit14 << 1) + (bit13 << 2) + (bit12 << 3) + 
            (bit11 << 4) + (bit10 << 5) + (bit9  << 6) + (bit8  << 7) +
            (bit7  << 8) + (bit6  << 9) + (bit5 << 10) + (bit4 << 11) +
            (bit3 << 12) + (bit2 << 13) + (bit1 << 14) + (bit0 << 15);
  
  printf("Row Width = %d\n",version);
  return 0;
}
